#include <REGX52.H>

#define DS1302_SECONDS	0x80
#define DS1302_MINUTES	0x82
#define DS1302_HOUR		0x84
#define DS1302_DATE		0x86
#define DS1302_MONTHS	0x88
#define DS1302_DAY		0x8A
#define DS1302_YEAR		0x8C
#define DS1302_WP		0x8E

sbit DS1302_CE = P3^5;
sbit DS1302_IO = P3^4;
sbit DS1302_SCLK = P3^6;

// 年 月 日 时 分 秒 周几
unsigned char DS1302_Time[] = {25, 8, 7, 23, 25, 12, 4};

/**
  * @brief   DS1302初始化方法
  * @details 
  * @param   
  * @retval  
  */
void DS1302_Init() {
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}

/**
  * @brief   写数据
  * @details 
  * @param   command 命令字
  * @param   byte 要写入的数据
  * @retval  
  */
void DS1302_WriteByte(unsigned char command, unsigned char byte) {
	unsigned char i;
	DS1302_CE = 1;
	
	// 写命令
	for (i = 0; i < 8; i++) {
		DS1302_IO = (command >> i) & 0x01;
		DS1302_SCLK = 1;
		// IO写入需要一定时间，所以SCLK切换要有一定延时
		DS1302_SCLK = 0;
	}
	// 写数据
	for (i = 0; i < 8; i++) {
		DS1302_IO = (byte >> i) & 0x01;
		DS1302_SCLK = 1;
		// 同上
		DS1302_SCLK = 0;
	}
	DS1302_CE = 0;
}

/**
  * @brief   读数据
  * @details 
  * @param   command WRITE命令字，方法会自动转换为READ
  * @retval  读出来的数据
  */
unsigned char DS1302_ReadByte(unsigned char command) {
	unsigned char i, byte = 0;
	command |= 0x01;
	DS1302_CE = 1;
	
	// 写命令
	for (i = 0; i < 8; i++) {
		DS1302_IO = (command >> i) & 0x01;
		DS1302_SCLK = 0;
		DS1302_SCLK = 1;
	}
	// 读数据
	for (i = 0; i < 8; i++) {
		DS1302_SCLK = 1;
		DS1302_SCLK = 0;
		if (DS1302_IO) {
			byte |= (0x01 << i);
		}
	}
	DS1302_CE = 0;
	DS1302_IO = 0;
	return byte;
}

/**
  * @brief   十进制转BCD码
  * @details 
  * @param   dec 十进制码，只支持两位
  * @retval  BCD
  */
unsigned char DecToBCD(unsigned char dec) {
	return dec / 10 * 16 + dec % 10;
}

/**
  * @brief   BCD码转十进制
  * @details 
  * @param   bcd BCD码
  * @retval  Dec
  */
unsigned char BCDToDec(unsigned char bcd) {
	return bcd / 16 * 10 + bcd % 16;
}

/**
  * @brief   设置时间初始值
  * @details 
  * @param   
  * @retval  
  */
void DS1302_SetTime() {
	DS1302_WriteByte(DS1302_WP, 0x00);
	
	DS1302_WriteByte(DS1302_YEAR, DecToBCD(DS1302_Time[0]));
	DS1302_WriteByte(DS1302_MONTHS, DecToBCD(DS1302_Time[1]));
	DS1302_WriteByte(DS1302_DATE, DecToBCD(DS1302_Time[2]));
	DS1302_WriteByte(DS1302_HOUR, DecToBCD(DS1302_Time[3]));
	DS1302_WriteByte(DS1302_MINUTES, DecToBCD(DS1302_Time[4]));
	DS1302_WriteByte(DS1302_SECONDS, DecToBCD(DS1302_Time[5]));
	DS1302_WriteByte(DS1302_DAY, DecToBCD(DS1302_Time[6]));
	
	DS1302_WriteByte(DS1302_WP, 0x80);
}

/**
  * @brief   获取时间到DS1302_Time
  * @details 
  * @param   
  * @retval  
  */
void DS1302_GetTime() {
	DS1302_Time[0] = BCDToDec(DS1302_ReadByte(DS1302_YEAR));
	DS1302_Time[1] = BCDToDec(DS1302_ReadByte(DS1302_MONTHS));
	DS1302_Time[2] = BCDToDec(DS1302_ReadByte(DS1302_DATE));
	DS1302_Time[3] = BCDToDec(DS1302_ReadByte(DS1302_HOUR));
	DS1302_Time[4] = BCDToDec(DS1302_ReadByte(DS1302_MINUTES));
	DS1302_Time[5] = BCDToDec(DS1302_ReadByte(DS1302_SECONDS));
	DS1302_Time[6] = BCDToDec(DS1302_ReadByte(DS1302_DAY));
}